package com.cardrive.entity;

import java.util.Timer;
import java.util.TimerTask;

import android.util.Log;

import com.cardrive.properties.CarProperties;

public class Engine {

	private final double C_BRAKING = 0.5;
	private final double MASS = 500;
	private final double C_DRAG = 0.4257;
	private final double C_RR = 12.8;

	public Pair currentVelocity;
	public Pair currentAcceleration;
	public Pair currentPosition;
	public Pair currentFLong;

	public Timer timer;

	private GearBox gearBox;

	public Engine() {
		gearBox = new GearBox(CarProperties.NUM_SHIFTS);

		currentVelocity = new Pair();
		currentAcceleration = new Pair();
		currentPosition = new Pair();
		currentFLong = new Pair();

		currentAcceleration.y = 1;
		currentVelocity.y = 1;

		currentAcceleration.x = 1;
		currentVelocity.x = 1;

		gearBox.setShift(1);

		timer = new Timer();

		timer.schedule(new TimerTask() {

			@Override
			public void run() {

				updateAcceleration(gearBox.getEngineForce(), false, 1);
				updateVelocity(1);
				updateCarPosition(1);

				Log.d("Engine", "v: " + currentVelocity.x);
				Log.d("Engine", "a: " + currentAcceleration.x);

			}
		}, 2000, 1000);

	}

	public void updateCarPosition(double diffTime) {

		currentPosition.x = currentPosition.x + diffTime * currentVelocity.x;
		currentPosition.y = currentPosition.y + diffTime * currentVelocity.y;

	}

	public void updateVelocity(double diffTime) {

		currentVelocity.x = currentVelocity.x + diffTime
				* currentAcceleration.x;
		currentVelocity.y = currentVelocity.y + diffTime
				* currentAcceleration.y;

	}

	public void updateAcceleration(double engineForce, boolean isBraking,
			double diffTime) {

		currentAcceleration.x = getFLong(engineForce, isBraking, diffTime).x
				/ MASS;
		currentAcceleration.y = getFLong(engineForce, isBraking, diffTime).y
				/ MASS;

	}

	public Pair getFTraction(Double engineForce, boolean isBraking) {

		if (isBraking) {
			Pair fBraking = new Pair();

			fBraking.x = -C_BRAKING * currentVelocity.x;
			fBraking.y = -C_BRAKING * currentVelocity.y;

			return fBraking;
		} else {
			Pair fTraction = new Pair();

			fTraction.x = currentVelocity.x * engineForce;
			fTraction.y = currentVelocity.y * engineForce;

			return fTraction;
		}
	}

	public Pair getFDrag(double diffTime) {

		Pair fDrag = new Pair();

		double speed = currentVelocity.getModule();

		fDrag.x = -C_DRAG * currentVelocity.x * speed;
		fDrag.y = -C_DRAG * currentVelocity.y * speed;

		return fDrag;
	}

	public Pair getFRollingResistance() {

		Pair fDrag = new Pair();

		fDrag.x = -C_RR * currentVelocity.x;
		fDrag.y = -C_RR * currentVelocity.y;

		return fDrag;
	}

	public Pair getFLong(Double engineForce, Boolean isBraking, double diffTime) {

		Pair fLong = new Pair();

		fLong.x = getFTraction(engineForce, isBraking).x + getFDrag(diffTime).x
				+ getFRollingResistance().x;
		fLong.y = getFTraction(engineForce, isBraking).y + getFDrag(diffTime).y
				+ getFRollingResistance().y;

		return fLong;
	}

	public void powerOff() {
		timer.cancel();
	}

}
